/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_MOVABLEOBJECT_H
#define M_MOVABLEOBJECT_H

#include "factory.h"
#include "vector3.h"
#include "aabb.h"
#include "scenenode.h"
#include "renderqueue.h"
#include "types.h"

#include <string>

namespace Engine
{
	class Ligth;
	/**
	*   Abstract class definining a movable object in a scene.
	*/
	class MovableObject
	{
		friend class SceneNode;
	public:
		/**
		*  Constructor
		*/
		MovableObject(const std::string& name);

        /**
		*   Virtual destructor
        */
        virtual ~MovableObject();

		/**
		*   Return name of object.
		*/
		const std::string& GetName()const;

		/**
		*   Retrieves the local axis-aligned bounding box for this object.
        */
        virtual const AABB& GetBoundingBox(void) const = 0;

		/**
		*   Retrieves the world axis-aligned bounding box for this object.
        */
        const AABB& GetWorldBoundingBox(void) const;

		/**
		*   Set visibility of the object.
		*/
		virtual void SetVisible(bool visible);

        /**
		*   Returns whether or not this object is supposed to be visible or not.
		*/
        virtual bool IsVisible(void) const;

		/**
		*   Sets the distance at which the object is no longer rendered.
		*/
		virtual void SetRenderingDistance(REAL dist);

		/**
		*   Gets the distance at which batches are no longer rendered.
		*/
		virtual REAL GetRenderingDistance(void) const;

		/**
		*   Method for supporting visitor pattern (see scene manager).
		*/
		virtual void Accept(MovableObjectVisitor* visitor) = 0;

		/**
		*   Returns the node to which this object is attached.
        */
        virtual SceneNode* GetParentNode(void) const;

		/**
		*   Returns true if this object is attached to a SceneNode.
		*/
        virtual bool IsAttached(void) const;

		/**
		*   Return true if object cast shadows
		*/
		bool IsCastShadow() const;

		/**
		*   Set object cast shadows.
		*/
		void SetCastShadow(bool val);

		/**
		*   Update object internal state, called form UpdateSceneGraph
		*/
		virtual void Update(){}

	private:
		/**
		*   Internal method called to notify the object that it has been attached to a node.
        */
        virtual void NotifyAttached(SceneNode* parent);

		/**
		*   Internal method called to notify the object that it has been detached from node.
        */
		virtual void NotifyDetached();

		/**
		*   Internal method by which the movable object must add Renderable subclass instances to the rendering queue.
        */
		virtual void UpdateRenderQueue(RenderQueue* queue, RenderQueue* shadowsQueue, const std::vector<LightPtr>& lightList) = 0;

	private:

		std::string m_name;
        SceneNode* m_parentNode;
        bool m_visible;
		REAL m_renderingDistance;
		mutable AABB m_worldAABB;
		bool m_castShadows;
	};

	/************************************************************************************************************************************/
	/**
	*   Interface definition for a factory class which produces a certain kind of MovableObject.
	*/
	class MovableObjectFactory: public Factory<MovableObject>
	{
	public:
		MovableObjectFactory():m_parameters(NULL){}
		/**
		*   Set additional parameters for object creation.
		*/
		void SetParameters(const NamedParameters* params){m_parameters = params;}

		/**
		*   Return pointer to parameters
		*/
		const NamedParameters* GetParameters(){return m_parameters;}
	private:
		const NamedParameters* m_parameters;
	};

}

#endif
